﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NetCoreCMS.Common;
using NetCoreCMS.IServices;
using NetCoreCMS.Models;
using NetCoreCMS.PayAPI.wxpay;

namespace NetCoreCMS.Web.Areas.Payments.Controllers
{
    public class WxApiPayController : AreasController
    {
        public IUser_rechargeService _user_recharge { get; set; }
        public IOrdersService _orders { get; set; }
        public ISite_paymentService _site_payment { get; set; }
        public IPaymentService _payment { get; set; }
        public IUser_point_logService _user_point_log { get; set; }
        public IBillsService _bills { get; set; }
        public IActionResult Index()
        {
            //获得订单信息
            int site_payment_id = 0; //订单支付方式
            string order_no = CMSRequest.GetFormString("pay_order_no", HttpContext).ToUpper();
            decimal order_amount = CMSRequest.GetFormDecimal("pay_order_amount", 0, HttpContext);

            //检查参数是否正确
            if (string.IsNullOrEmpty(order_no) || order_amount == 0)
            {
                return ToError("对不起，您提交的参数有误！");       
            }
            //===============================判断订单==================================
            if (order_no.StartsWith("R")) //R开头为在线充值订单
            {
                User_recharge model = _user_recharge.GetModel(order_no);
                if (model == null)
                {
                    return ToError("对不起，您充值的订单号不存在或已删除！");     
                }
                if (model.amount != order_amount)
                {
                    return ToError("对不起，您充值的订单金额与实际金额不一致！");            
                }
                site_payment_id = model.payment_id; //站点支付方式ID
            }
            else //B开头为商品订单
            {
                Orders model = _orders.GetModel(order_no);
                if (model == null)
                {
                    return ToError("对不起，您支付的订单号不存在或已删除！");   
                }
                if (model.order_amount != order_amount)
                {
                    return ToError("对不起，您支付的订单金额与实际金额不一致！");  
                }
                site_payment_id = model.payment_id; //站点支付方式ID
            }
            var site_paymentModel = _site_payment.GetList().FirstOrDefault(a=>a.payment_id==site_payment_id);
            var paymentModel = _payment.GetModel(site_payment_id);
            //调用【网页授权获取用户信息】接口获取用户的openid和access_token
            JsApiConfig jsApiConfig = new JsApiConfig(site_paymentModel, paymentModel, sysConfig, HttpContext);
            WxPayData data = new WxPayData();
            data.SetValue("appid", jsApiConfig.AppId);
            data.SetValue("redirect_uri", Utils.UrlEncode(jsApiConfig.Redirect_url));
            data.SetValue("response_type", "code");
            data.SetValue("scope", "snsapi_base");
            data.SetValue("state", order_no + "#wechat_redirect"); //传入订单号
            string url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + data.ToUrl();
            try
            {
                //触发微信返回code码         
                return Redirect(url);//Redirect函数会抛出ThreadAbortException异常，不用处理这个异常
            }
            catch (System.Threading.ThreadAbortException ex)
            {
                return Content(ex.Message);
            }
        }
        public static string wxJsApiParam { get; set; } //H5调起JS API参数
        public static string returnUrl { get; set; } //支付成功跳转的地址
        public IActionResult jsapipay()
        {
            int site_payment_id = 0; //订单支付方式
            string openid = CMSRequest.GetQueryString("openid",HttpContext);
            string order_no = CMSRequest.GetQueryString("order_no",HttpContext).ToUpper();
            decimal order_amount = 0; //订单金额
            string subject1 = string.Empty; //订单备注1
            string subject2 = string.Empty; //订单备注2

            //检查参数是否正确
            if (string.IsNullOrEmpty(openid) || string.IsNullOrEmpty(order_no))
            {
                return ToError("对不起，获取OPENID参数有误！");
            }
            if (order_no.StartsWith("R")) //R开头为在线充值订单
            {
                User_recharge model = _user_recharge.GetModel(order_no);
                if (model == null)
                {
                    return ToError("对不起，您充值的订单号不存在或已删除！");
                }
                order_amount = model.amount; //订单金额
                subject1 = "充值订单";
                subject2 = "用户名：" + model.user_name;
                site_payment_id = model.payment_id; //站点支付方式ID
            }
            else //B开头为商品订单
            {
                Orders model = _orders.GetModel(order_no);
                if (model == null)
                {
                    return ToError("对不起，您支付的订单号不存在或已删除！");
                }
                order_amount = model.order_amount; //订单金额
                subject1 = "商品订单";
                if (model.user_id > 0)
                {
                    subject2 = "用户名：" + model.user_name;
                }
                else
                {
                    subject2 = "匿名用户";
                }
                site_payment_id = model.payment_id; //站点支付方式ID
            }
            var site_paymentModel = _site_payment.GetList().FirstOrDefault(a => a.payment_id == site_payment_id);
            var paymentModel = _payment.GetModel(site_payment_id);
            //JSAPI支付预处理
            try
            {
                //统一下单
                string sendUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
                JsApiConfig jsApiConfig = new JsApiConfig(site_paymentModel, paymentModel, sysConfig, HttpContext);
                WxPayData data = new WxPayData();
                data.SetValue("body", subject1); //商品描述
                data.SetValue("detail", subject2); //商品详情
                data.SetValue("out_trade_no", order_no); //商户订单号
                data.SetValue("total_fee", (Convert.ToDouble(order_amount) * 100).ToString()); //订单总金额,以分为单位
                data.SetValue("trade_type", "JSAPI"); //交易类型
                data.SetValue("openid", openid); //公众账号ID
                data.SetValue("appid", jsApiConfig.AppId); //公众账号ID
                data.SetValue("mch_id", jsApiConfig.Partner); //商户号
                data.SetValue("nonce_str", JsApiPay.GenerateNonceStr()); //随机字符串
                data.SetValue("notify_url", jsApiConfig.Notify_url); //异步通知url
                data.SetValue("spbill_create_ip", CMSRequest.GetClientUserIp(HttpContext)); //终端IP
                data.SetValue("sign", data.MakeSign(jsApiConfig.Key)); //签名
                string xml = data.ToXml(); //转换成XML
                var startTime = DateTime.Now; //开始时间
                string response = HttpService.Post(xml, sendUrl, false, 6); //发送请求
                var endTime = DateTime.Now; //结束时间
                int timeCost = (int)((endTime - startTime).TotalMilliseconds); //计算所用时间
                WxPayData result = new WxPayData();
                result.FromXml(response, jsApiConfig.Key);
                JsApiPay.ReportCostTime(site_paymentModel, paymentModel, sysConfig, HttpContext, sendUrl, timeCost, result); //测速上报

                //获取H5调起JS API参数
                WxPayData jsApiParam = new WxPayData();
                jsApiParam.SetValue("appId", result.GetValue("appid"));
                jsApiParam.SetValue("timeStamp", JsApiPay.GenerateTimeStamp());
                jsApiParam.SetValue("nonceStr", JsApiPay.GenerateNonceStr());
                jsApiParam.SetValue("package", "prepay_id=" + result.GetValue("prepay_id"));
                jsApiParam.SetValue("signType", "MD5");
                jsApiParam.SetValue("paySign", jsApiParam.MakeSign(jsApiConfig.Key));
                wxJsApiParam = jsApiParam.ToJson();

                //支付成功后跳转的URL
                returnUrl = "/Web/Payment/Index?action=succeed&order_no=" + order_no;
            }
            catch (Exception ex)
            {
                return ToError("调用JSAPI下单失败！"+ex.Message+ex.StackTrace+ex.InnerException);
            }
            ViewBag.wxJsApiParam = wxJsApiParam;
            ViewBag.returnUrl = returnUrl;
            return View();
        }
        public async Task<IActionResult> notify_url()
        {
            try
            {
                int site_payment_id = 0;
                WxPayData requestData = new WxPayData();
                await requestData.GetRequest(HttpContext); //获取微信传过来的参数
                if (!requestData.IsSet("transaction_id"))
                {
                    //若transaction_id不存在，则立即返回结果给微信支付后台
                    WxPayData res = new WxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", "支付结果中微信订单号不存在");
                    return Content(res.ToXml());
                }
                //获取订单信息
                string transaction_id = requestData.GetValue("transaction_id").ToString(); //微信支付订单号
                string order_no = requestData.GetValue("out_trade_no").ToString().ToUpper(); //商户订单号
                string total_fee = requestData.GetValue("total_fee").ToString(); //获取总金额
                if (order_no.StartsWith("R")) //充值订单
                {
                    site_payment_id = _user_recharge.GetModel(order_no).payment_id;
                }
                else if (order_no.StartsWith("B")) //商品订单
                {
                    site_payment_id = _orders.GetModel(order_no).payment_id;
                }
                if (site_payment_id == 0)
                {
                    //若订单查询失败，则立即返回结果给微信支付后台
                    WxPayData res = new WxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", "订单不存在或已删除");
                    return Content(res.ToXml());
                }
                var site_paymentModel = _site_payment.GetList().FirstOrDefault(a => a.payment_id == site_payment_id);
                var paymentModel = _payment.GetModel(site_payment_id);
                //开始验证订单
                WxPayData notifyData = await JsApiPay.GetNotifyData(site_paymentModel, paymentModel, sysConfig, HttpContext);
                //查询订单，判断订单真实性
                if (!QueryOrder(transaction_id, site_paymentModel, paymentModel))
                {
                    //若订单查询失败，则立即返回结果给微信支付后台
                    WxPayData res = new WxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", "订单查询失败");
                    return Content(res.ToXml());
                }

                if (order_no.StartsWith("R")) //充值订单
                {
                    User_recharge model = _user_recharge.GetModel(order_no);
                    if (model == null)
                    {
                        WxPayData res = new WxPayData();
                        res.SetValue("return_code", "FAIL");
                        res.SetValue("return_msg", "该订单号不存在");
                        return Content(res.ToXml());
                    }
                    if (model.status == 1) //已成功
                    {
                        WxPayData res = new WxPayData();
                        res.SetValue("return_code", "SUCCESS");
                        res.SetValue("return_msg", "OK");
                        return Content(res.ToXml());
                    }
                    if (model.amount != (decimal.Parse(total_fee) / 100))
                    {
                        WxPayData res = new WxPayData();
                        res.SetValue("return_code", "FAIL");
                        res.SetValue("return_msg", "订单金额和支付金额不相符");
                        return Content(res.ToXml());
                    }
                    bool result = _user_recharge.Confirm(order_no);
                    if (!result)
                    {
                        WxPayData res = new WxPayData();
                        res.SetValue("return_code", "FAIL");
                        res.SetValue("return_msg", "修改订单状态失败");
                        return Content(res.ToXml());
                    }
                }
                else if (order_no.StartsWith("B")) //商品订单
                {
                    Orders model = _orders.GetModel(order_no);
                    if (model == null)
                    {
                        WxPayData res = new WxPayData();
                        res.SetValue("return_code", "FAIL");
                        res.SetValue("return_msg", "该订单号不存在");
                        return Content(res.ToXml());
                    }
                    if (model.payment_status == 2) //已付款
                    {
                        WxPayData res = new WxPayData();
                        res.SetValue("return_code", "SUCCESS");
                        res.SetValue("return_msg", "OK");
                        return Content(res.ToXml());
                    }
                    if (model.order_amount != (decimal.Parse(total_fee) / 100))
                    {
                        WxPayData res = new WxPayData();
                        res.SetValue("return_code", "FAIL");
                        res.SetValue("return_msg", "订单金额和支付金额不相符");
                        return Content(res.ToXml());
                    }
                    bool result = _orders.UpdateField(order_no, "trade_no='" + transaction_id + "',status=2,payment_status=2,payment_time='" + DateTime.Now + "'");
                    if (!result)
                    {
                        WxPayData res = new WxPayData();
                        res.SetValue("return_code", "FAIL");
                        res.SetValue("return_msg", "修改订单状态失败");
                        return Content(res.ToXml());
                    }
                    //扣除积分
                    if (model.point < 0)
                    {
                        _user_point_log.Add(model.user_id, model.user_name, model.point, "换购扣除积分，订单号：" + model.order_no, false);
                    }
                }
            }
            catch (Exception ex)
            {
                _bills.Add(new Bills { remark = ex.Message+ex.StackTrace+ex.InnerException });
            }

            //返回成功通知
            WxPayData res1 = new WxPayData();
            res1.SetValue("return_code", "SUCCESS");
            res1.SetValue("return_msg", "OK");
            return Content(res1.ToXml());
        }
        public IActionResult return_url()
        {
            int site_payment_id = 0; //订单支付方式
            //获取code码，以获取openid和access_token
            string code = CMSRequest.GetQueryString("code",HttpContext);
            //获取传过来的订单号
            string order_no = CMSRequest.GetQueryString("state",HttpContext).ToUpper();

            //检查参数是否正确
            if (string.IsNullOrEmpty(code) || string.IsNullOrEmpty(order_no))
            {
                return ToError("出错了，获取CODE回调参数有误！");
            }
            if (order_no.StartsWith("R")) //充值订单
            {
                site_payment_id = _user_recharge.GetModel(order_no).payment_id;
            }
            else if (order_no.StartsWith("B")) //商品订单
            {
                site_payment_id = _orders.GetModel(order_no).payment_id;
            }
            var site_paymentModel = _site_payment.GetList().FirstOrDefault(a => a.payment_id == site_payment_id);
            var paymentModel = _payment.GetModel(site_payment_id);
            //获取openid及access_token的url
            try
            {
                JsApiConfig jsApiConfig = new JsApiConfig(site_paymentModel, paymentModel, sysConfig, HttpContext);
                WxPayData data = new WxPayData();
                data.SetValue("appid", jsApiConfig.AppId);
                data.SetValue("secret", jsApiConfig.AppSecret);
                data.SetValue("code", code);
                data.SetValue("grant_type", "authorization_code");
                string url = "https://api.weixin.qq.com/sns/oauth2/access_token?" + data.ToUrl();

                //请求url以获取数据
                string result = HttpService.Get(url);
                //获取用户openid
                Dictionary<string, object> dic = JsonHelper.DataRowFromJSON(result);
                string openid = (string)dic["openid"];
                //跳转转值到处理页面
                return Redirect("jsapipay?openid=" + openid + "&order_no=" + order_no);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.ToString());
            }
        }
        //查询订单
        private bool QueryOrder(string transaction_id, Site_payment model, Payment payModel)
        {
            WxPayData req = new WxPayData();
            req.SetValue("transaction_id", transaction_id);
            WxPayData res = JsApiPay.OrderQuery(model, payModel, sysConfig, HttpContext, req);
            if (res.GetValue("return_code").ToString() == "SUCCESS" &&
                res.GetValue("result_code").ToString() == "SUCCESS")
            {
                return true;
            }
            else
            {
                return false;
            }
        }

    }
}